/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** ************************************************************************************************
 * \file     Firewall_Dio.c                                                                  *
 * \brief    Semidrive Firewall GPIO Driver                                                             *
 *                                                                                                 *
 **************************************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************************************
 *                                      Include header files                                       *
 **************************************************************************************************/
#if (defined(CFG_PLATFORM_MCAL))
#include "RegHelper.h"
#endif /** #if (defined(CFG_PLATFORM_MCAL)) */

#include "Firewall_Dio_Ip.h"

/***************************************************************************************************
 *                                 Private Macro definition                                        *
 **************************************************************************************************/
/** \brief The offset bit of privilege mode permission for domain0. */
#define RULESPACE_DOM0_PRIV_BIT       (4U)
/** \brief The offset bit of user mode permission for domain0. */
#define RULESPACE_DOM0_USR_BIT        (6U)
/** \brief The offset bit of privilege mode permission for domain1. */
#define RULESPACE_DOM1_PRIV_BIT       (12U)
/** \brief The offset bit of user mode permission for domain1. */
#define RULESPACE_DOM1_USR_BIT        (14U)
/** \brief The offset bit of privilege mode permission for domain2. */
#define RULESPACE_DOM2_PRIV_BIT       (20U)
/** \brief The offset bit of user mode permission for domain2. */
#define RULESPACE_DOM2_USR_BIT        (22U)
/** \brief The offset bit of privilege mode permission for domain3. */
#define RULESPACE_DOM3_PRIV_BIT       (28U)
/** \brief The offset bit of user mode permission for domain3. */
#define RULESPACE_DOM3_USR_BIT        (30U)
/** \brief The offset bit of privilege mode permission for domain4. */
#define RULESPACE_DOM4_PRIV_BIT       (4U)
/** \brief The offset bit of user mode permission for domain4. */
#define RULESPACE_DOM4_USR_BIT        (6U)
/** \brief The offset bit of privilege mode permission for domain5. */
#define RULESPACE_DOM5_PRIV_BIT       (12U)
/** \brief The offset bit of user mode permission for domain5. */
#define RULESPACE_DOM5_USR_BIT        (14U)
/** \brief The offset bit of privilege mode permission for domain6. */
#define RULESPACE_DOM6_PRIV_BIT       (20U)
/** \brief The offset bit of user mode permission for domain6. */
#define RULESPACE_DOM6_USR_BIT        (22U)
/** \brief The offset bit of privilege mode permission for domain7. */
#define RULESPACE_DOM7_PRIV_BIT       (28U)
/** \brief The offset bit of user mode permission for domain7. */
#define RULESPACE_DOM7_USR_BIT        (30U)
/** \brief The offset bit of privilege mode permission for domain8. */
#define RULESPACE_DOM8_PRIV_BIT       (4U)
/** \brief The offset bit of user mode permission for domain8. */
#define RULESPACE_DOM8_USR_BIT        (6U)
/** \brief The offset bit of privilege mode permission for domain9. */
#define RULESPACE_DOM9_PRIV_BIT       (12U)
/** \brief The offset bit of user mode permission for domain9. */
#define RULESPACE_DOM9_USR_BIT        (14U)
/** \brief The offset bit of privilege mode permission for domain10. */
#define RULESPACE_DOM10_PRIV_BIT      (20U)
/** \brief The offset bit of user mode permission for domain10. */
#define RULESPACE_DOM10_USR_BIT       (22U)
/** \brief The offset bit of privilege mode permission for domain11. */
#define RULESPACE_DOM11_PRIV_BIT      (28U)
/** \brief The offset bit of user mode permission for domain11. */
#define RULESPACE_DOM11_USR_BIT       (30U)
/** \brief The offset bit of privilege mode permission for domain12. */
#define RULESPACE_DOM12_PRIV_BIT      (4U)
/** \brief The offset bit of user mode permission for domain12. */
#define RULESPACE_DOM12_USR_BIT       (6U)
/** \brief The offset bit of privilege mode permission for domain13. */
#define RULESPACE_DOM13_PRIV_BIT      (12U)
/** \brief The offset bit of user mode permission for domain13. */
#define RULESPACE_DOM13_USR_BIT       (14U)
/** \brief The offset bit of privilege mode permission for domain14. */
#define RULESPACE_DOM14_PRIV_BIT      (20U)
/** \brief The offset bit of user mode permission for domain14. */
#define RULESPACE_DOM14_USR_BIT       (22U)
/** \brief The offset bit of privilege mode permission for domain15. */
#define RULESPACE_DOM15_PRIV_BIT      (28U)
/** \brief The offset bit of user mode permission for domain15. */
#define RULESPACE_DOM15_USR_BIT       (30U)

/** \brief The mask bit of permission none. */
#define RULESPACE_PER_NONE                ((uint32_t)0xF0F0F0F0U)
/** \brief The mask bit of specified domain permission. */
#define RULESPACE_PER_MASK(n)             (~((uint32_t)0xFU << (n)))

/** \brief The offset address of the gpio permission0 register. */
#define FIREWALL_GPIO_DOM_PER0N_0         ((uint32_t)0x00U)
/** \brief The size of the gpio permission0 register. */
#define FIREWALL_GPIO_DOM_PER0N_SIZE      ((uint32_t)0x14U)
/** \brief The offset address of the gpio permission0 register for different cores. */
#define FIREWALL_GPIO_DOM_PER0N_ADDR(n)                                        \
    (FIREWALL_GPIO_DOM_PER0N_0 + ((n)*FIREWALL_GPIO_DOM_PER0N_SIZE))

/** \brief The offset address of the gpio permission1 register. */
#define FIREWALL_GPIO_DOM_PER1N_0         ((uint32_t)0x04U)
/** \brief The size of the gpio permission1 register. */
#define FIREWALL_GPIO_DOM_PER1N_SIZE      ((uint32_t)0x14U)
/** \brief The offset address of the gpio permission1 register for different cores. */
#define FIREWALL_GPIO_DOM_PER1N_ADDR(n)                                        \
    (FIREWALL_GPIO_DOM_PER1N_0 + ((n)*FIREWALL_GPIO_DOM_PER1N_SIZE))

/** \brief The offset address of the gpio permission1 register. */
#define FIREWALL_GPIO_DOM_PER2N_0         ((uint32_t)0x08U)
/** \brief The size of the gpio permission1 register. */
#define FIREWALL_GPIO_DOM_PER2N_SIZE      ((uint32_t)0x14U)
/** \brief The offset address of the gpio permission1 register for different cores. */
#define FIREWALL_GPIO_DOM_PER2N_ADDR(n)                                        \
    (FIREWALL_GPIO_DOM_PER2N_0 + ((n)*FIREWALL_GPIO_DOM_PER2N_SIZE))

/** \brief The offset address of the gpio permission1 register. */
#define FIREWALL_GPIO_DOM_PER3N_0         ((uint32_t)0x0CU)
/** \brief The size of the gpio permission1 register. */
#define FIREWALL_GPIO_DOM_PER3N_SIZE      ((uint32_t)0x14U)
/** \brief The offset address of the gpio permission1 register for different cores. */
#define FIREWALL_GPIO_DOM_PER3N_ADDR(n)                                        \
    (FIREWALL_GPIO_DOM_PER3N_0 + ((n)*FIREWALL_GPIO_DOM_PER3N_SIZE))

/** \brief The offset address of the gpio permission lock register. */
#define FIREWALL_GPIO_DOM_PER_LOCKN_0     ((uint32_t)0x10U)
/** \brief The size of the gpio permission lock register. */
#define FIREWALL_GPIO_DOM_PER_LOCKN_SIZE  ((uint32_t)0x14U)
/** \brief The bit mask of locking the gpio permission. */
#define FIREWALL_GPIO_DOM_PER_LOCK        ((uint32_t)0xFFFFUL)
/** \brief The offset address of the gpio permission lock register for different cores. */
#define FIREWALL_GPIO_DOM_PER_LOCKN_ADDR(n)                                    \
    (FIREWALL_GPIO_DOM_PER_LOCKN_0 + ((n)*FIREWALL_GPIO_DOM_PER_LOCKN_SIZE))

/** \brief The offset address of the gpio core select register. */
#define FIREWALL_GPIO_DGSELN_0      ((uint32_t)0x140U)
/** \brief The size of the gpio core select register. */
#define FIREWALL_GPIO_DGSELN_SIZE   ((uint32_t)0x04U)
/** \brief The offset bit of the gpio core select. */
#define FIREWALL_GPIO_RGN_DGSEL_BIT (1U)
/** \brief The bit mask of enabling the gpio permission control. */
#define FIREWALL_GPIO_RGN_EN        ((uint32_t)1UL)
/** \brief The bit mask of locking the gpio permission control. */
#define FIREWALL_GPIO_RGN_LOCK      ((uint32_t)(1UL << 31U))
/** \brief The offset address of the gpio core select register for different pin channels. */
#define FIREWALL_GPIO_DGSELN_ADDR(n)                                           \
    (FIREWALL_GPIO_DGSELN_0 + ((n)*FIREWALL_GPIO_DGSELN_SIZE))

#if (defined(CFG_PLATFORM_MCAL))
#define FIREWALL_START_SEC_CODE
#include "Firewall_MemMap.h"
#endif /** #if (defined(CFG_PLATFORM_MCAL)) */


/***************************************************************************************************
 *                                  Private Function Declarations                                  *
 **************************************************************************************************/
/**
 * brief Configure the gpio pin rule space.
 *
 * This function is called by Firewall_DioRuleSpaceConfigure().
 *
 * param[in] dioChannelCfg The pointer to the gpio pin configurations.
 * param[in] dioCoreId The id of the core.
 *
 * return The result of this function.
 * details - return FIREWALL_E_OK : Configure the gpio rule space success.
 *          - return FIREWALL_E_NULL_POINTER : The pointer is a NULL_PTR.
 *          - return FIREWALL_E_GPIO_CHANNEL_NUM : The number of the gpio pin channels is unvalid.
 */
static lld_status_t Firewall_DioSelectCore(
    const Firewall_DioChannelCfgType *dioChannelCfg, uint8_t dioCoreId);

/**
 * brief Configure the permissions of the gpio pin for the core.
 *
 * This function is called by Firewall_DioRuleSpaceConfigure().
 *
 * param[in] dioCoreCfgPtr The pointer to the gpio pin configurations.
 *
 * return The result of this function.
 * details - return FIREWALL_E_OK : Configure the gpio rule space perimissions success.
 *          - return FIREWALL_E_NULL_POINTER : The pointer is a NULL_PTR.
 *          - return FIREWALL_E_GPIO_CORE_ID : The id of the core is unvalid.
 */
static lld_status_t Firewall_DioPermissionConfigure(
    const Firewall_DioCoreCfgType *dioCoreCfgPtr);

/***************************************************************************************************
 *                                  Global Function Declarations                                   *
 **************************************************************************************************/
/**
 * \brief Configure the gpio rule space and perimissions.
 *
 * This function Configure the gpio rule space and perimissions.
 * This function should be called only once.
 *
 * param[in] dioRuleSpaceCfgPtr the configuration of pin permission.
 * param[in] dioCoreCfgNum the number of cores.
 *
 * return The result of this function.
 * details - return FIREWALL_E_OK : Configure the gpio rule space and perimissions success.
 *          - return FIREWALL_E_NULL_POINTER : The pointer is a NULL_PTR.
 *          - return FIREWALL_E_GPIO_CORE_NUM : The number of the core configurations is unvalid.
 */
lld_status_t Firewall_DioRuleSpaceConfigure(
    const Firewall_DioCoreCfgType *dioRuleSpaceCfgPtr, uint16_t dioCoreCfgNum)
{
    lld_status_t ret_val = (lld_status_t)FIREWALL_E_OK;
    uint8_t coreId;

    /* #10 Check the parameters. */
    if (NULL == dioRuleSpaceCfgPtr)
    {
        ret_val = (lld_status_t)FIREWALL_E_NULL_POINTER;
    }
    else if (FIREWALL_GPIO_CORE_MAXNUM < dioCoreCfgNum)
    {
        ret_val = (lld_status_t)FIREWALL_E_DIO_CORE_NUM;
    }
    else
    {
        /* #20 Configure the rule of gpio pins. */
        for (coreId = 0U; coreId < dioCoreCfgNum; ++coreId)
        {
            /* Assign gpio pins to the specified core. */
            ret_val = Firewall_DioSelectCore(
                &dioRuleSpaceCfgPtr[coreId].dioChannelCfg,
                dioRuleSpaceCfgPtr[coreId].dioCoreId);
            if ((lld_status_t)FIREWALL_E_OK == ret_val)
            {
                /* Configure the permissions of gpio pins for the core. */
                ret_val =
                    Firewall_DioPermissionConfigure(&dioRuleSpaceCfgPtr[coreId]);
            } /* else not needed */

            if ((lld_status_t)FIREWALL_E_OK != ret_val)
            {
                break;
            } /* else not needed */
        }

        if ((lld_status_t)FIREWALL_E_OK == ret_val)
        {
            /* #30 Lock the permissions of gpio pins for different cores. */
            for (coreId = 0U; coreId < FIREWALL_GPIO_CORE_MAXNUM; ++coreId)
            {
                writel(FIREWALL_GPIO_DOM_PER_LOCK,
                    FIREWALL_APB_GPIO_SF1_BASE +
                    FIREWALL_GPIO_DOM_PER_LOCKN_ADDR(coreId));
                writel(FIREWALL_GPIO_DOM_PER_LOCK,
                    FIREWALL_APB_GPIO_SF2_BASE +
                    FIREWALL_GPIO_DOM_PER_LOCKN_ADDR(coreId));
                writel(FIREWALL_GPIO_DOM_PER_LOCK,
                    FIREWALL_APB_GPIO_LP_BASE +
                    FIREWALL_GPIO_DOM_PER_LOCKN_ADDR(coreId));
            }
        }
    }

    return ret_val;
}

/***************************************************************************************************
 *                                  Private Function Declarations                                  *
 **************************************************************************************************/
/**
 * brief Configure the gpio pin rule space.
 *
 * This function is called by Firewall_DioRuleSpaceConfigure().
 *
 * param[in] dioChannelCfg The pointer to the gpio pin configurations.
 * param[in] dioCoreId The id of the core.
 *
 * return The result of this function.
 * details - return FIREWALL_E_OK : Configure the gpio rule space success.
 *          - return FIREWALL_E_NULL_POINTER : The pointer is a NULL_PTR.
 *          - return FIREWALL_E_GPIO_CHANNEL_NUM : The number of the gpio pin channels is unvalid.
 */
static lld_status_t Firewall_DioSelectCore(
    const Firewall_DioChannelCfgType *dioChannelCfg, uint8_t dioCoreId)
{
    lld_status_t ret_val = (lld_status_t)FIREWALL_E_OK;

    uint32_t ChannelID;
    uint32_t dioBase = 0U;
    uint32_t dioIndex = 0U;
    uint16_t channel_cfgnum;
    uint16_t channel_num;
    uint32_t temp_val;

    /* #10 Check the parameters. */
    if (NULL == dioChannelCfg->dioChannelID)
    {
        ret_val = (lld_status_t)FIREWALL_E_NULL_POINTER;
    }
    else if (FIREWALL_GPIO_CHANNEL_MAXNUM < dioChannelCfg->dioChannelNum)
    {
        ret_val = (lld_status_t)FIREWALL_E_DIO_CHANNEL_NUM;
    }
    else
    {
        channel_cfgnum = dioChannelCfg->dioChannelNum;

        /* #20 Assign gpio pins to the specified core. */
        for (channel_num = 0U; channel_num < channel_cfgnum; ++channel_num)
        {
            ChannelID = dioChannelCfg->dioChannelID[channel_num];
            ret_val = Firewall_DioGetChannelInfo(ChannelID, &dioIndex, &dioBase);
            if ((lld_status_t)FIREWALL_E_OK != ret_val)
            {
                ret_val = (lld_status_t)FIREWALL_E_DIO_CHANNEL_ID;
            }
            if ((lld_status_t)FIREWALL_E_OK == ret_val)
            {
                if (FIREWALL_GPIO_RGN_LOCK == (FIREWALL_GPIO_RGN_LOCK &
                   readl(dioBase + FIREWALL_GPIO_DGSELN_ADDR(dioIndex))))
                {
                    continue;
                }
                /* Select the assignment of the gpio pin. */
                writel((uint32_t)dioCoreId << FIREWALL_GPIO_RGN_DGSEL_BIT,
                        dioBase + FIREWALL_GPIO_DGSELN_ADDR(dioIndex));

                /* Enable and lock the assignment of the gpio pin. */
                temp_val = readl(dioBase +
                                FIREWALL_GPIO_DGSELN_ADDR(dioIndex));
                writel(temp_val | FIREWALL_GPIO_RGN_EN,
                        dioBase + FIREWALL_GPIO_DGSELN_ADDR(dioIndex));

                temp_val = readl(dioBase +
                                FIREWALL_GPIO_DGSELN_ADDR(dioIndex));
                writel(temp_val | FIREWALL_GPIO_RGN_LOCK,
                        dioBase + FIREWALL_GPIO_DGSELN_ADDR(dioIndex));
            } /* else not needed */
        }
    }

    return ret_val;
}

/**
 * brief Configure the permissions of the rulespace.
 *
 * This function is called by Firewall_DioPermissionConfigure().
 *
 * param[in] RulespaceCfgPtr The pointer to the rulespace configurations.
 *
 * return The result of this function.
 * details - return FIREWALL_E_OK : Configure rulespace perimissions success.
 *          - return FIREWALL_E_MAC_DOMAIN_ID : The pointer is a NULL_PTR.
 */
lld_status_t Firewall_RulespaceConfig(Rulespace_CfgType *RulespaceCfgPtr)
{
    lld_status_t ret_val = (lld_status_t)FIREWALL_E_OK;

    /* Set all domains permission none if not used or configured. */
    uint32_t domPer0 = RULESPACE_PER_NONE;
    uint32_t domPer1 = RULESPACE_PER_NONE;
    uint32_t domPer2 = RULESPACE_PER_NONE;
    uint32_t domPer3 = RULESPACE_PER_NONE;

    /* Config lock/unlock domain permission.
     * Domain 0 permission is configured as RW.
     */
    domPer0 |= (uint32_t)PERMISSION_RW
                        << RULESPACE_DOM0_PRIV_BIT;
    domPer0 |= (uint32_t)PERMISSION_RW
                        << RULESPACE_DOM0_USR_BIT;
    /* Configure permissions of gpio pins for the specified core. */
    switch (RulespaceCfgPtr->domainNum)
    {
        /* domain0 has been configured before. */
        case 0:
        /* domain1 is unlock domian. */
        case 1:
            break;
        case 2:
            domPer0 &= RULESPACE_PER_MASK(RULESPACE_DOM2_PRIV_BIT);
            domPer0 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM2_PRIV_BIT;
            domPer0 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM2_USR_BIT;
            break;
        case 3:
            domPer0 &= RULESPACE_PER_MASK(RULESPACE_DOM3_PRIV_BIT);
            domPer0 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM3_PRIV_BIT;
            domPer0 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM3_USR_BIT;
            break;
        case 4:
            domPer1 &= RULESPACE_PER_MASK(RULESPACE_DOM4_PRIV_BIT);
            domPer1 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM4_PRIV_BIT;
            domPer1 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM4_USR_BIT;
            break;
        case 5:
            domPer1 &= RULESPACE_PER_MASK(RULESPACE_DOM5_PRIV_BIT);
            domPer1 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM5_PRIV_BIT;
            domPer1 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM5_USR_BIT;
            break;
        case 6:
            domPer1 &= RULESPACE_PER_MASK(RULESPACE_DOM6_PRIV_BIT);
            domPer1 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM6_PRIV_BIT;
            domPer1 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM6_USR_BIT;
            break;
        case 7:
            domPer1 &= RULESPACE_PER_MASK(RULESPACE_DOM7_PRIV_BIT);
            domPer1 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM7_PRIV_BIT;
            domPer1 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM7_USR_BIT;
            break;
        case 8:
            domPer2 &= RULESPACE_PER_MASK(RULESPACE_DOM8_PRIV_BIT);
            domPer2 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM8_PRIV_BIT;
            domPer2 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM8_USR_BIT;
            break;
        case 9:
            domPer2 &= RULESPACE_PER_MASK(RULESPACE_DOM9_PRIV_BIT);
            domPer2 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM9_PRIV_BIT;
            domPer2 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM9_USR_BIT;
            break;
        case 10:
            domPer2 &= RULESPACE_PER_MASK(RULESPACE_DOM10_PRIV_BIT);
            domPer2 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM10_PRIV_BIT;
            domPer2 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM10_USR_BIT;
            break;
        case 11:
            domPer2 &= RULESPACE_PER_MASK(RULESPACE_DOM11_PRIV_BIT);
            domPer2 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM11_PRIV_BIT;
            domPer2 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM11_USR_BIT;
            break;
        case 12:
            domPer3 &= RULESPACE_PER_MASK(RULESPACE_DOM12_PRIV_BIT);
            domPer3 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM12_PRIV_BIT;
            domPer3 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM12_USR_BIT;
            break;
        case 13:
            domPer3 &= RULESPACE_PER_MASK(RULESPACE_DOM13_PRIV_BIT);
            domPer3 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM13_PRIV_BIT;
            domPer3 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM13_USR_BIT;
            break;
        case 14:
            domPer3 &= RULESPACE_PER_MASK(RULESPACE_DOM14_PRIV_BIT);
            domPer3 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM14_PRIV_BIT;
            domPer3 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM14_USR_BIT;
            break;
        case 15:
            domPer3 &= RULESPACE_PER_MASK(RULESPACE_DOM15_PRIV_BIT);
            domPer3 |= ((uint32_t)RulespaceCfgPtr->privilegedPermission)
                        << RULESPACE_DOM15_PRIV_BIT;
            domPer3 |= ((uint32_t)RulespaceCfgPtr->userPermission)
                        << RULESPACE_DOM15_USR_BIT;
            break;

        default:   /* domain id is invalid */
        {
            ret_val = (lld_status_t)FIREWALL_E_MAC_DOMAIN_ID;
            break;
        }
    }

    /* Save permission config to Rulespace config instance. */
    RulespaceCfgPtr->domainPer0 = domPer0;
    RulespaceCfgPtr->domainPer1 = domPer1;
    RulespaceCfgPtr->domainPer2 = domPer2;
    RulespaceCfgPtr->domainPer3 = domPer3;

    return ret_val;
}

/**
 * brief Configure the permissions of the gpio pin for the core.
 *
 * This function is called by Firewall_DioRuleSpaceConfigure().
 *
 * param[in] dioCoreCfgPtr The pointer to the gpio pin configurations.
 *
 * return The result of this function.
 * details - return FIREWALL_E_OK : Configure the gpio rule space perimissions success.
 *          - return FIREWALL_E_NULL_POINTER : The pointer is a NULL_PTR.
 *          - return FIREWALL_E_GPIO_CORE_ID : The id of the core is unvalid.
 */
static lld_status_t Firewall_DioPermissionConfigure(
    const Firewall_DioCoreCfgType *dioCoreCfgPtr)
{
    lld_status_t ret_val = (lld_status_t)FIREWALL_E_OK;
    Rulespace_CfgType DioRulespaceCfg;

    uint16_t channelNum;
    uint16_t channelCfgNum;
    uint32_t channelId;
    uint32_t dioBase;

    /* #10 Check the parameters. */
    if (NULL == dioCoreCfgPtr)
    {
        ret_val = (lld_status_t)FIREWALL_E_NULL_POINTER;
    }
    else
    {
        channelCfgNum = dioCoreCfgPtr->dioChannelCfg.dioChannelNum;

        for (channelNum = 0U; channelNum < channelCfgNum; ++channelNum)
        {
            channelId = dioCoreCfgPtr->dioChannelCfg.dioChannelID[channelNum];
            ret_val = Firewall_DioGetChannelInfo(channelId, NULL, &dioBase);

            /* #10 Check the lock state */
            if (((lld_status_t)FIREWALL_E_OK == ret_val) &&
                (FIREWALL_GPIO_DOM_PER_LOCK != (FIREWALL_GPIO_DOM_PER_LOCK &
                readl(dioBase + FIREWALL_GPIO_DOM_PER_LOCKN_ADDR(dioCoreCfgPtr->dioCoreId)))))
            {
                /* Update Dio permission configs. */
                DioRulespaceCfg.domainNum = dioCoreCfgPtr->didId;
                DioRulespaceCfg.rulespaceNum = dioCoreCfgPtr->dioCoreId;
                DioRulespaceCfg.privilegedPermission = dioCoreCfgPtr->dioPrivilegedPermission;
                DioRulespaceCfg.userPermission = dioCoreCfgPtr->dioUserPermission;

                ret_val = Firewall_RulespaceConfig(&DioRulespaceCfg);

                if ((lld_status_t)FIREWALL_E_OK == ret_val)
                {
                    /* #20 Set permission registers. */
                    writel(DioRulespaceCfg.domainPer0, dioBase +
                            FIREWALL_GPIO_DOM_PER0N_ADDR(DioRulespaceCfg.rulespaceNum));
                    writel(DioRulespaceCfg.domainPer1, dioBase +
                            FIREWALL_GPIO_DOM_PER1N_ADDR(DioRulespaceCfg.rulespaceNum));
                    writel(DioRulespaceCfg.domainPer2, dioBase +
                            FIREWALL_GPIO_DOM_PER2N_ADDR(DioRulespaceCfg.rulespaceNum));
                    writel(DioRulespaceCfg.domainPer3, dioBase +
                            FIREWALL_GPIO_DOM_PER3N_ADDR(DioRulespaceCfg.rulespaceNum));
                }
            }
        }
    }

    return ret_val;
}

#if (defined(CFG_PLATFORM_MCAL))
#define FIREWALL_STOP_SEC_CODE
#include "Firewall_MemMap.h"
#endif /** #if (defined(CFG_PLATFORM_MCAL)) */

#ifdef __cplusplus
}
#endif

/* End of file */
